home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pcl / sptmbr16.lha / macros.lisp < prev    next >
Lisp/Scheme  |  1993-01-07  |  25KB  |  744 lines

  1. ;;;-*-Mode:LISP; Package:(PCL (LISP WALKER)); Base:10; Syntax:Common-lisp -*-
  2. ;;;
  3. ;;; *************************************************************************
  4. ;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
  5. ;;; All rights reserved.
  6. ;;;
  7. ;;; Use and copying of this software and preparation of derivative works
  8. ;;; based upon this software are permitted.  Any distribution of this
  9. ;;; software or derivative works must comply with all applicable United
  10. ;;; States export control laws.
  11. ;;; 
  12. ;;; This software is made available AS IS, and Xerox Corporation makes no
  13. ;;; warranty about the software, its performance or its conformity to any
  14. ;;; specification.
  15. ;;; 
  16. ;;; Any person obtaining a copy of this software is requested to send their
  17. ;;; name and post office or electronic mail address to:
  18. ;;;   CommonLoops Coordinator
  19. ;;;   Xerox PARC
  20. ;;;   3333 Coyote Hill Rd.
  21. ;;;   Palo Alto, CA 94304
  22. ;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
  23. ;;;
  24. ;;; Suggestions, comments and requests for improvements are also welcome.
  25. ;;; *************************************************************************
  26. ;;;
  27. ;;; Macros global variable definitions, and other random support stuff used
  28. ;;; by the rest of the system.
  29. ;;;
  30. ;;; For simplicity (not having to use eval-when a lot), this file must be
  31. ;;; loaded before it can be compiled.
  32. ;;;
  33.  
  34. (in-package :pcl)
  35.  
  36. (proclaim '(declaration
  37.          #-Genera values          ;I use this so that Zwei can remind
  38.                       ;me what values a function returns.
  39.          
  40.          #-Genera arglist          ;Tells me what the pretty arglist
  41.                       ;of something (which probably takes
  42.                       ;&rest args) is.
  43.  
  44.          #-Genera indentation     ;Tells ZWEI how to indent things
  45.                           ;like defclass.
  46.          class
  47.          variable-rebinding
  48.          pcl-fast-call
  49.          method-name
  50.          method-lambda-list
  51.          ))
  52.  
  53. ;;; Age old functions which CommonLisp cleaned-up away.  They probably exist
  54. ;;; in other packages in all CommonLisp implementations, but I will leave it
  55. ;;; to the compiler to optimize into calls to them.
  56. ;;;
  57. ;;; Common Lisp BUG:
  58. ;;;    Some Common Lisps define these in the Lisp package which causes
  59. ;;;    all sorts of lossage.  Common Lisp should explictly specify which
  60. ;;;    symbols appear in the Lisp package.
  61. ;;;
  62. (eval-when (compile load eval)
  63.  
  64. (defmacro memq (item list) `(member ,item ,list :test #'eq))
  65. (defmacro assq (item list) `(assoc ,item ,list :test #'eq))
  66. (defmacro rassq (item list) `(rassoc ,item ,list :test #'eq))
  67. (defmacro delq (item list) `(delete ,item ,list :test #'eq))
  68. (defmacro posq (item list) `(position ,item ,list :test #'eq))
  69. (defmacro neq (x y) `(not (eq ,x ,y)))
  70.  
  71.  
  72. (defun make-caxr (n form)
  73.   (if (< n 4)
  74.       `(,(nth n '(car cadr caddr cadddr)) ,form)
  75.       (make-caxr (- n 4) `(cddddr ,form))))
  76.  
  77. (defun make-cdxr (n form)
  78.   (cond ((zerop n) form)
  79.     ((< n 5) `(,(nth n '(identity cdr cddr cdddr cddddr)) ,form))
  80.     (t (make-cdxr (- n 4) `(cddddr ,form)))))
  81. )
  82.  
  83. (defun true (&rest ignore) (declare (ignore ignore)) t)
  84. (defun false (&rest ignore) (declare (ignore ignore)) nil)
  85. (defun zero (&rest ignore) (declare (ignore ignore)) 0)
  86.  
  87. (defun make-plist (keys vals)
  88.   (if (null vals)
  89.       ()
  90.       (list* (car keys)
  91.          (car vals)
  92.          (make-plist (cdr keys) (cdr vals)))))
  93.  
  94. (defun remtail (list tail)
  95.   (if (eq list tail) () (cons (car list) (remtail (cdr list) tail))))
  96.  
  97. ;;; ONCE-ONLY does the same thing as it does in zetalisp.  I should have just
  98. ;;; lifted it from there but I am honest.  Not only that but this one is
  99. ;;; written in Common Lisp.  I feel a lot like bootstrapping, or maybe more
  100. ;;; like rebuilding Rome.
  101. (defmacro once-only (vars &body body)
  102.   (let ((gensym-var (gensym))
  103.         (run-time-vars (gensym))
  104.         (run-time-vals (gensym))
  105.         (expand-time-val-forms ()))
  106.     (dolist (var vars)
  107.       (push `(if (or (symbolp ,var)
  108.                      (numberp ,var)
  109.                      (and (listp ,var)
  110.               (member (car ,var) '(quote function))))
  111.                  ,var
  112.                  (let ((,gensym-var (gensym)))
  113.                    (push ,gensym-var ,run-time-vars)
  114.                    (push ,var ,run-time-vals)
  115.                    ,gensym-var))
  116.             expand-time-val-forms))    
  117.     `(let* (,run-time-vars
  118.             ,run-time-vals
  119.             (wrapped-body
  120.           (let ,(mapcar #'list vars (reverse expand-time-val-forms))
  121.         ,@body)))
  122.        `(let ,(mapcar #'list (reverse ,run-time-vars)
  123.                  (reverse ,run-time-vals))
  124.       ,wrapped-body))))
  125.  
  126. (eval-when (compile load eval)
  127. (defun extract-declarations (body &optional environment)
  128.   ;;(declare (values documentation declarations body))
  129.   (let (documentation declarations form)
  130.     (when (and (stringp (car body))
  131.            (cdr body))
  132.       (setq documentation (pop body)))
  133.     (block outer
  134.       (loop
  135.     (when (null body) (return-from outer nil))
  136.     (setq form (car body))
  137.     (when (block inner
  138.         (loop (cond ((not (listp form))
  139.                  (return-from outer nil))
  140.                 ((eq (car form) 'declare)
  141.                  (return-from inner 't))
  142.                 (t
  143.                  (multiple-value-bind (newform macrop)
  144.                   (macroexpand-1 form environment)
  145.                    (if (or (not (eq newform form)) macrop)
  146.                    (setq form newform)
  147.                  (return-from outer nil)))))))
  148.       (pop body)
  149.       (dolist (declaration (cdr form))
  150.         (push declaration declarations)))))
  151.     (values documentation
  152.         (and declarations `((declare ,.(nreverse declarations))))
  153.         body)))
  154. )
  155.  
  156. (defun get-declaration (name declarations &optional default)
  157.   (dolist (d declarations default)
  158.     (dolist (form (cdr d))
  159.       (when (and (consp form) (eq (car form) name))
  160.     (return-from get-declaration (cdr form))))))
  161.  
  162.  
  163. #+Lucid
  164. (eval-when (compile load eval)
  165.   (eval `(defstruct ,(intern "FASLESCAPE" (find-package 'lucid)))))
  166.  
  167. (defvar *keyword-package* (find-package 'keyword))
  168.  
  169. (defun make-keyword (symbol)
  170.   (intern (symbol-name symbol) *keyword-package*))
  171.  
  172. (eval-when (compile load eval)
  173.  
  174. (defun string-append (&rest strings)
  175.   (setq strings (copy-list strings))        ;The explorer can't even
  176.                         ;rplaca an &rest arg?
  177.   (do ((string-loc strings (cdr string-loc)))
  178.       ((null string-loc)
  179.        (apply #'concatenate 'string strings))
  180.     (rplaca string-loc (string (car string-loc)))))
  181. )
  182.  
  183. (defun symbol-append (sym1 sym2 &optional (package *package*))
  184.   (intern (string-append sym1 sym2) package))
  185.  
  186. (defmacro check-member (place list &key (test #'eql) (pretty-name place))
  187.   (once-only (place list)
  188.     `(or (member ,place ,list :test ,test)
  189.          (error "The value of ~A, ~S is not one of ~S."
  190.                 ',pretty-name ,place ,list))))
  191.  
  192. (defmacro alist-entry (alist key make-entry-fn)
  193.   (once-only (alist key)
  194.     `(or (assq ,key ,alist)
  195.      (progn (setf ,alist (cons (,make-entry-fn ,key) ,alist))
  196.         (car ,alist)))))
  197.  
  198. ;;; A simple version of destructuring-bind.
  199.  
  200. ;;; This does no more error checking than CAR and CDR themselves do.  Some
  201. ;;; attempt is made to be smart about preserving intermediate values.  It
  202. ;;; could be better, although the only remaining case should be easy for
  203. ;;; the compiler to spot since it compiles to PUSH POP.
  204. ;;;
  205. ;;; Common Lisp BUG:
  206. ;;;    Common Lisp should have destructuring-bind.
  207. ;;;    
  208. (defmacro destructuring-bind (pattern form &body body)
  209.   (multiple-value-bind (ignore declares body)
  210.       (extract-declarations body)
  211.     (declare (ignore ignore))
  212.     (multiple-value-bind (setqs binds)
  213.     (destructure pattern form)
  214.       `(let ,binds
  215.      ,@declares
  216.      ,@setqs
  217.      (progn .destructure-form.)
  218.      . ,body))))
  219.  
  220. (eval-when (compile load eval)
  221. (defun destructure (pattern form)
  222.   ;;(declare (values setqs binds))
  223.   (let ((*destructure-vars* ())
  224.     (setqs ()))
  225.     (declare (special *destructure-vars*))
  226.     (setq *destructure-vars* '(.destructure-form.)
  227.       setqs (list `(setq .destructure-form. ,form))
  228.       form '.destructure-form.)
  229.     (values (nconc setqs (nreverse (destructure-internal pattern form)))
  230.         (delete nil *destructure-vars*))))
  231.  
  232. (defun destructure-internal (pattern form)
  233.   ;; When we are called, pattern must be a list.  Form should be a symbol
  234.   ;; which we are free to setq containing the value to be destructured.
  235.   ;; Optimizations are performed for the last element of pattern cases.
  236.   ;; we assume that the compiler is smart about gensyms which are bound
  237.   ;; but only for a short period of time.
  238.   (declare (special *destructure-vars*))
  239.   (let ((gensym (gensym))
  240.     (pending-pops 0)
  241.     (var nil)
  242.     (setqs ()))
  243.     (labels
  244.         ((make-pop (var form pop-into)
  245.        (prog1 
  246.          (cond ((zerop pending-pops)
  247.             `(progn ,(and var `(setq ,var (car ,form)))
  248.                 ,(and pop-into `(setq ,pop-into (cdr ,form)))))
  249.            ((null pop-into)
  250.             (and var `(setq ,var ,(make-caxr pending-pops form))))
  251.            (t
  252.             `(progn (setq ,pop-into ,(make-cdxr pending-pops form))
  253.                 ,(and var `(setq ,var (pop ,pop-into))))))
  254.          (setq pending-pops 0))))
  255.       (do ((pat pattern (cdr pat)))
  256.       ((null pat) ())
  257.     (if (symbolp (setq var (car pat)))
  258.         (progn
  259.           #-:coral (unless (memq var '(nil ignore))
  260.              (push var *destructure-vars*))
  261.           #+:coral (push var *destructure-vars*)          
  262.           (cond ((null (cdr pat))
  263.              (push (make-pop var form ()) setqs))
  264.             ((symbolp (cdr pat))
  265.              (push (make-pop var form (cdr pat)) setqs)
  266.              (push (cdr pat) *destructure-vars*)
  267.              (return ()))
  268.             #-:coral
  269.             ((memq var '(nil ignore)) (incf pending-pops))
  270.             #-:coral
  271.             ((memq (cadr pat) '(nil ignore))
  272.              (push (make-pop var form ()) setqs)
  273.              (incf pending-pops 1))
  274.             (t
  275.              (push (make-pop var form form) setqs))))
  276.         (progn
  277.           (push `(let ((,gensym ()))
  278.                ,(make-pop gensym
  279.                   form
  280.                   (if (symbolp (cdr pat)) (cdr pat) form))
  281.                ,@(nreverse
  282.                (destructure-internal
  283.                  (if (consp pat) (car pat) pat)
  284.                  gensym)))
  285.             setqs)
  286.           (when (symbolp (cdr pat))
  287.         (push (cdr pat) *destructure-vars*)
  288.         (return)))))
  289.       setqs)))
  290. )
  291.  
  292.  
  293. (defmacro collecting-once (&key initial-value)
  294.    `(let* ((head ,initial-value)
  295.            (tail ,(and initial-value `(last head))))
  296.           (values #'(lambda (value)
  297.                            (if (null head)
  298.                                (setq head (setq tail (list value)))
  299.                    (unless (memq value head)
  300.                  (setq tail
  301.                        (cdr (rplacd tail (list value)))))))
  302.           #'(lambda nil head))))
  303.  
  304. (defmacro doplist ((key val) plist &body body &environment env)
  305.   (multiple-value-bind (doc decls bod)
  306.       (extract-declarations body env)
  307.     (declare (ignore doc))
  308.     `(let ((.plist-tail. ,plist) ,key ,val)
  309.        ,@decls
  310.        (loop (when (null .plist-tail.) (return nil))
  311.          (setq ,key (pop .plist-tail.))
  312.          (when (null .plist-tail.)
  313.            (error "Malformed plist in doplist, odd number of elements."))
  314.          (setq ,val (pop .plist-tail.))
  315.          (progn ,@bod)))))
  316.  
  317. (defmacro if* (condition true &rest false)
  318.   `(if ,condition ,true (progn ,@false)))
  319.  
  320. (defmacro dolist-carefully ((var list improper-list-handler) &body body)
  321.   `(let ((,var nil)
  322.          (.dolist-carefully. ,list))
  323.      (loop (when (null .dolist-carefully.) (return nil))
  324.            (if (consp .dolist-carefully.)
  325.                (progn
  326.                  (setq ,var (pop .dolist-carefully.))
  327.                  ,@body)
  328.                (,improper-list-handler)))))
  329.  
  330.   ;;   
  331. ;;;;;; printing-random-thing
  332.   ;;
  333. ;;; Similar to printing-random-object in the lisp machine but much simpler
  334. ;;; and machine independent.
  335. (defmacro printing-random-thing ((thing stream) &body body)
  336.   (once-only (stream)
  337.   `(progn (format ,stream "#<")
  338.       ,@body
  339.       (format ,stream " ")
  340.       (printing-random-thing-internal ,thing ,stream)
  341.       (format ,stream ">"))))
  342.  
  343. (defun printing-random-thing-internal (thing stream)
  344.   (declare (ignore thing stream))
  345.   nil)
  346.  
  347.   ;;   
  348. ;;;;;; 
  349.   ;;
  350.  
  351. (defun capitalize-words (string &optional (dashes-p t))
  352.   (let ((string (copy-seq (string string))))
  353.     (declare (string string))
  354.     (do* ((flag t flag)
  355.       (length (length string) length)
  356.       (char nil char)
  357.       (i 0 (+ i 1)))
  358.      ((= i length) string)
  359.       (setq char (elt string i))
  360.       (cond ((both-case-p char)
  361.          (if flag
  362.          (and (setq flag (lower-case-p char))
  363.               (setf (elt string i) (char-upcase char)))
  364.          (and (not flag) (setf (elt string i) (char-downcase char))))
  365.          (setq flag nil))
  366.         ((char-equal char #\-)
  367.          (setq flag t)
  368.          (unless dashes-p (setf (elt string i) #\space)))
  369.         (t (setq flag nil))))))
  370.  
  371. #-(or lucid kcl)
  372. (eval-when (compile load eval)
  373. ;(warn "****** Things will go faster if you fix define-compiler-macro")
  374. )
  375.  
  376. (defmacro define-compiler-macro (name arglist &body body)
  377.   #+(or lucid kcl)
  378.   `(#+lucid lcl:def-compiler-macro #+kcl si::define-compiler-macro
  379.         ,name ,arglist
  380.         ,@body)
  381.   #-(or kcl lucid)
  382.   (declare (ignore name arglist body))
  383.   #-(or kcl lucid)
  384.   nil)
  385.  
  386.  
  387. ;;;
  388. ;;; FIND-CLASS
  389. ;;;
  390. ;;; This is documented in the CLOS specification.
  391. ;;;
  392. (defvar *find-class* (make-hash-table :test #'eq))
  393.  
  394. (defun make-constant-function (value)
  395.   #'(lambda (object)
  396.       (declare (ignore object))
  397.       value))
  398.  
  399. (defun function-returning-nil (x)
  400.   (declare (ignore x))
  401.   nil)
  402.  
  403. (defun function-returning-t (x)
  404.   (declare (ignore x))
  405.   t)
  406.  
  407. (defmacro find-class-cell-class (cell)
  408.   `(car ,cell))
  409.  
  410. (defmacro find-class-cell-predicate (cell)
  411.   `(cadr ,cell))
  412.  
  413. (defmacro find-class-cell-make-instance-function-keys (cell)
  414.   `(cddr ,cell))
  415.  
  416. (defmacro make-find-class-cell (class-name)
  417.   (declare (ignore class-name))
  418.   '(list* nil #'function-returning-nil nil))
  419.  
  420. (defun find-class-cell (symbol &optional dont-create-p)
  421.   (or (gethash symbol *find-class*)
  422.       (unless dont-create-p
  423.     (unless (legal-class-name-p symbol)
  424.       (error "~S is not a legal class name." symbol))
  425.     (setf (gethash symbol *find-class*) (make-find-class-cell symbol)))))
  426.  
  427. (defvar *create-classes-from-internal-structure-definitions-p* t)
  428.  
  429. (defun find-class-from-cell (symbol cell &optional (errorp t))
  430.   (or (find-class-cell-class cell)
  431.       (and *create-classes-from-internal-structure-definitions-p*
  432.            (structure-type-p symbol)
  433.            (find-structure-class symbol))
  434.       (cond ((null errorp) nil)
  435.         ((legal-class-name-p symbol)
  436.          (error "No class named: ~S." symbol))
  437.         (t
  438.          (error "~S is not a legal class name." symbol)))))
  439.  
  440. (defun find-class-predicate-from-cell (symbol cell &optional (errorp t))
  441.   (unless (find-class-cell-class cell)
  442.     (find-class-from-cell symbol cell errorp))
  443.   (find-class-cell-predicate cell))
  444.  
  445. (defun legal-class-name-p (x)
  446.   (and (symbolp x)
  447.        (not (keywordp x))))
  448.  
  449. (defun find-class (symbol &optional (errorp t) environment)
  450.   (declare (ignore environment))
  451.   (find-class-from-cell
  452.    symbol (find-class-cell symbol errorp) errorp))
  453.  
  454. (defun find-class-predicate (symbol &optional (errorp t) environment)
  455.   (declare (ignore environment))
  456.   (find-class-predicate-from-cell 
  457.    symbol (find-class-cell symbol errorp) errorp))
  458.  
  459. #-setf
  460. (defsetf find-class (symbol &optional (errorp t) environment) (new-value)
  461.   (declare (ignore errorp environment))
  462.   `(SETF\ PCL\ FIND-CLASS ,new-value ,symbol))
  463.  
  464. (defun #-setf SETF\ PCL\ FIND-CLASS #+setf (setf find-class) (new-value symbol)
  465.   (declare (special *boot-state*))
  466.   (if (legal-class-name-p symbol)
  467.       (let ((cell (find-class-cell symbol)))
  468.     (setf (find-class-cell-class cell) new-value)
  469.     (when (or (eq *boot-state* 'complete)
  470.           (eq *boot-state* 'braid))
  471.       (setf (find-class-cell-predicate cell)
  472.         (symbol-function (class-predicate-name new-value)))
  473.       (when (and new-value (not (forward-referenced-class-p new-value)))
  474.         (dolist (keys+aok (find-class-cell-make-instance-function-keys cell))
  475.           (update-initialize-info-internal
  476.            (initialize-info new-value (car keys+aok) nil (cdr keys+aok))
  477.            'make-instance-function)))))
  478.       (error "~S is not a legal class name." symbol)))
  479.  
  480. #-setf
  481. (defsetf find-class-predicate (symbol &optional (errorp t) environment) (new-value)
  482.   (declare (ignore errorp environment))
  483.   `(SETF\ PCL\ FIND-CLASS-PREDICATE ,new-value ,symbol))
  484.  
  485. (defun #-setf SETF\ PCL\ FIND-CLASS-PREDICATE #+setf (setf find-class-predicate)
  486.           (new-value symbol)
  487.   (if (legal-class-name-p symbol)
  488.       (setf (find-class-cell-predicate (find-class-cell symbol)) new-value)
  489.       (error "~S is not a legal class name." symbol)))
  490.  
  491. (defun find-wrapper (symbol)
  492.   (class-wrapper (find-class symbol)))
  493.  
  494. #|| ; Anything that used this should use eval instead.
  495. (defun reduce-constant (old)
  496.   (let ((new (eval old)))
  497.     (if (eq new old)
  498.     new
  499.     (if (constantp new)
  500.         (reduce-constant new)
  501.         new))))
  502. ||#
  503.  
  504. (defmacro gathering1 (gatherer &body body)
  505.   `(gathering ((.gathering1. ,gatherer))
  506.      (macrolet ((gather1 (x) `(gather ,x .gathering1.)))
  507.        ,@body)))
  508.  
  509. ;;;
  510. ;;; 
  511. ;;; 
  512. (defmacro vectorizing (&key (size 0))
  513.   `(let* ((limit ,size)
  514.       (result (make-array limit))
  515.       (index 0))
  516.      (values #'(lambda (value)
  517.          (if (= index limit)
  518.              (error "vectorizing more elements than promised.")
  519.              (progn
  520.                (setf (svref result index) value)
  521.                (incf index)
  522.                value)))
  523.          #'(lambda () result))))
  524.  
  525. ;;;
  526. ;;; These are augmented definitions of list-elements and list-tails from
  527. ;;; iterate.lisp.  These versions provide the extra :by keyword which can
  528. ;;; be used to specify the step function through the list.
  529. ;;;
  530. (defmacro *list-elements (list &key (by #'cdr))
  531.   `(let ((tail ,list))
  532.      #'(lambda (finish)
  533.      (if (endp tail)
  534.          (funcall finish)
  535.          (prog1 (car tail)
  536.                 (setq tail (funcall ,by tail)))))))
  537.  
  538. (defmacro *list-tails (list &key (by #'cdr))
  539.    `(let ((tail ,list))
  540.       #'(lambda (finish)
  541.           (prog1 (if (endp tail)
  542.              (funcall finish)
  543.              tail)
  544.              (setq tail (funcall ,by tail))))))
  545.  
  546. (defmacro function-funcall (form &rest args)
  547.   #-cmu `(funcall ,form ,@args)
  548.   #+cmu `(funcall (the function ,form) ,@args))
  549.  
  550. (defmacro function-apply (form &rest args)
  551.   #-cmu `(apply ,form ,@args)
  552.   #+cmu `(apply (the function ,form) ,@args))
  553.  
  554.  
  555. ;;;
  556. ;;; Convert a function name to its standard setf function name.  We have to
  557. ;;; do this hack because not all Common Lisps have yet converted to having
  558. ;;; setf function specs.
  559. ;;;
  560. ;;; In a port that does have setf function specs you can use those just by
  561. ;;; making the obvious simple changes to these functions.  The rest of PCL
  562. ;;; believes that there are function names like (SETF <foo>), this is the
  563. ;;; only place that knows about this hack.
  564. ;;;
  565. (eval-when (compile load eval)
  566. ; In 15e (and also 16c), using the built in setf mechanism costs 
  567. ; a hash table lookup every time a setf function is called.
  568. ; Uncomment the next line to use the built in setf mechanism.
  569. ;#+cmu (pushnew :setf *features*) 
  570. )
  571.  
  572. (eval-when (compile load eval)
  573.  
  574. #-setf
  575. (defvar *setf-function-names* (make-hash-table :size 200 :test #'eq))
  576.  
  577. (defun get-setf-function-name (name)
  578.   #+setf `(setf ,name)
  579.   #-setf
  580.   (or (gethash name *setf-function-names*)
  581.       (setf (gethash name *setf-function-names*)
  582.         (let ((pkg (symbol-package name)))
  583.           (if pkg
  584.           (intern (format nil
  585.                   "SETF ~A ~A"
  586.                   (package-name pkg)
  587.                   (symbol-name name))
  588.               *the-pcl-package*)
  589.           (make-symbol (format nil "SETF ~A" (symbol-name name))))))))
  590.  
  591. ;;;
  592. ;;; Call this to define a setf macro for a function with the same behavior as
  593. ;;; specified by the SETF function cleanup proposal.  Specifically, this will
  594. ;;; cause: (SETF (FOO a b) x) to expand to (|SETF FOO| x a b).
  595. ;;;
  596. ;;; do-standard-defsetf                  A macro interface for use at top level
  597. ;;;                                      in files.  Unfortunately, users may
  598. ;;;                                      have to use this for a while.
  599. ;;;                                      
  600. ;;; do-standard-defsetfs-for-defclass    A special version called by defclass.
  601. ;;; 
  602. ;;; do-standard-defsetf-1                A functional interface called by the
  603. ;;;                                      above, defmethod and defgeneric.
  604. ;;;                                      Since this is all a crock anyways,
  605. ;;;                                      users are free to call this as well.
  606. ;;;
  607. (defmacro do-standard-defsetf (&rest function-names)
  608.   `(eval-when (compile load eval)
  609.      (dolist (fn-name ',function-names) (do-standard-defsetf-1 fn-name))))
  610.  
  611. (defun do-standard-defsetfs-for-defclass (accessors)
  612.   (dolist (name accessors) (do-standard-defsetf-1 name)))
  613.  
  614. (defun do-standard-defsetf-1 (function-name)
  615.   #+setf
  616.   (declare (ignore function-name))
  617.   #+setf nil
  618.   #-setf
  619.   (unless (and (setfboundp function-name)
  620.            (get function-name 'standard-setf))
  621.     (setf (get function-name 'standard-setf) t)
  622.     (let* ((setf-function-name (get-setf-function-name function-name)))
  623.     
  624.       #+Genera
  625.       (let ((fn #'(lambda (form)
  626.             (lt::help-defsetf
  627.               '(&rest accessor-args) '(new-value) function-name 'nil
  628.               `(`(,',setf-function-name ,new-value .,accessor-args))
  629.               form))))
  630.     (setf (get function-name 'lt::setf-method) fn
  631.           (get function-name 'lt::setf-method-internal) fn))
  632.  
  633.       #+Lucid
  634.       (lucid::set-simple-setf-method 
  635.     function-name
  636.     #'(lambda (form new-value)
  637.         (let* ((bindings (mapcar #'(lambda (x) `(,(gensym) ,x))
  638.                      (cdr form)))
  639.            (vars (mapcar #'car bindings)))
  640.           ;; This may wrap spurious LET bindings around some form,
  641.           ;;   but the PQC compiler will unwrap then.
  642.           `(LET (,.bindings)
  643.          (,setf-function-name ,new-value . ,vars)))))
  644.       
  645.       #+kcl
  646.       (let ((helper (gensym)))
  647.     (setf (macro-function helper)
  648.           #'(lambda (form env)
  649.           (declare (ignore env))
  650.           (let* ((loc-args (butlast (cdr form)))
  651.              (bindings (mapcar #'(lambda (x) `(,(gensym) ,x)) loc-args))
  652.              (vars (mapcar #'car bindings)))
  653.             `(let ,bindings
  654.                (,setf-function-name ,(car (last form)) ,@vars)))))
  655.     (eval `(defsetf ,function-name ,helper)))
  656.       #+Xerox
  657.       (flet ((setf-expander (body env)
  658.            (declare (ignore env))
  659.            (let ((temps
  660.                (mapcar #'(lambda (x) (declare (ignore x)) (gensym))
  661.                    (cdr body)))
  662.              (forms (cdr body))
  663.              (vars (list (gensym))))
  664.          (values temps
  665.              forms
  666.              vars
  667.              `(,setf-function-name ,@vars ,@temps)
  668.              `(,function-name ,@temps)))))
  669.     (let ((setf-method-expander (intern (concatenate 'string
  670.                                  (symbol-name function-name)
  671.                                  "-setf-expander")
  672.                      (symbol-package function-name))))
  673.       (setf (get function-name :setf-method-expander) setf-method-expander
  674.         (symbol-function setf-method-expander) #'setf-expander)))
  675.       
  676.       #-(or Genera Lucid kcl Xerox)
  677.       (eval `(defsetf ,function-name (&rest accessor-args) (new-value)
  678.            (let* ((bindings (mapcar #'(lambda (x) `(,(gensym) ,x)) accessor-args))
  679.               (vars (mapcar #'car bindings)))
  680.           `(let ,bindings
  681.               (,',setf-function-name ,new-value ,@vars)))))
  682.       
  683.       )))
  684.  
  685. (defun setfboundp (symbol)
  686.   #+Genera (not (null (get-properties (symbol-plist symbol)
  687.                       'lt::(derived-setf-function trivial-setf-method
  688.                         setf-equivalence setf-method))))
  689.   #+Lucid  (locally
  690.          (declare (special lucid::*setf-inverse-table*
  691.                    lucid::*simple-setf-method-table*
  692.                    lucid::*setf-method-expander-table*))
  693.          (or (gethash symbol lucid::*setf-inverse-table*)
  694.          (gethash symbol lucid::*simple-setf-method-table*)
  695.          (gethash symbol lucid::*setf-method-expander-table*)))
  696.   #+kcl    (or (get symbol 'si::setf-method)
  697.            (get symbol 'si::setf-update-fn)
  698.            (get symbol 'si::setf-lambda))
  699.   #+Xerox  (or (get symbol :setf-inverse)
  700.            (get symbol 'il:setf-inverse)
  701.            (get symbol 'il:setfn)
  702.            (get symbol :shared-setf-inverse)
  703.            (get symbol :setf-method-expander)
  704.            (get symbol 'il:setf-method-expander))
  705.   #+:coral (or (get symbol 'ccl::setf-inverse)
  706.            (get symbol 'ccl::setf-method-expander))
  707.   #+cmu (fboundp `(setf ,symbol))
  708.   #-(or Genera Lucid KCL Xerox :coral cmu) nil)
  709.  
  710. );eval-when
  711.  
  712.  
  713. ;;;
  714. ;;; PCL, like user code, must endure the fact that we don't have a properly
  715. ;;; working setf.  Many things work because they get mentioned by a defclass
  716. ;;; or defmethod before they are used, but others have to be done by hand.
  717. ;;; 
  718. (do-standard-defsetf
  719.   class-wrapper                                 ;***
  720.   generic-function-name
  721.   method-function-plist
  722.   method-function-get
  723.   plist-value
  724.   object-plist
  725.   gdefinition
  726.   slot-value-using-class
  727.   )
  728.  
  729. (defsetf slot-value set-slot-value)
  730.  
  731. (defvar *redefined-functions* nil)
  732.  
  733. (defmacro original-definition (name)
  734.   `(get ,name ':definition-before-pcl))
  735.  
  736. (defun redefine-function (name new)
  737.   (pushnew name *redefined-functions*)
  738.   (unless (original-definition name)
  739.     (setf (original-definition name)
  740.       (symbol-function name)))
  741.   (setf (symbol-function name)
  742.     (symbol-function new)))
  743.  
  744.